/*------------------------------------------------------------------------
 *  Copyright (C) 2011  Luis M. de la Cruz Salas
 *
 *  This file is part of TUNA
 *
 *  TUNA is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  TUNA is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ------------------------------------------------------------------------*/

#ifndef _SCALAREQUATION_H_
#define _SCALAREQUATION_H_

#include "Tuna.hpp"
#include "Equations/GeneralEquation.hpp"

namespace Tuna {

template <typename T>  class ScalarEquation;
  
template <typename T>  
struct Typeinfo <ScalarEquation<T> > {
  typedef typename Typeinfo<T>::prec_t prec_t;
  enum { Dim = Typeinfo<T>::Dim };
};

/*! 
 ***************************************************************************
 *  This class derives from GeneralEquation through B & N trick.
 *  In this class some particular variables and methods for scalar PDE's
 *  are defined. This class is used to model FVM discretized general scalar 
 *  PDE equations.
 ***************************************************************************
 *  \author  Luis M. de la Cruz [ Mon May  4 16:20:22 CDT 2009 ]
 ***************************************************************************
 */

template<typename Tscheme>
class ScalarEquation : public GeneralEquation<ScalarEquation<Tscheme> >
{
  using GeneralEquation<ScalarEquation<Tscheme> >::name;

public:
  typedef typename Typeinfo<Tscheme>::prec_t prec_t;
  typedef typename TunaArray<prec_t, Typeinfo<Tscheme>::Dim >::tiny floatTinyArray_t; 
  typedef typename TunaArray<int, Typeinfo<Tscheme>::Dim >::tiny intTinyArray_t;
  typedef typename TunaArray<prec_t, Typeinfo<Tscheme>::Dim >::huge ScalarField;

  // // #ifdef WITH_GenMat
  typedef SparseMatrix< Diagonal< prec_t, Typeinfo<Tscheme>::Dim > > DiagMat;
  // // #else
  // //  typedef DiagonalMatrix<prec_t, Typeinfo<Tscheme>::Dim > DiagMat;
  // // #endif

  ScalarEquation() : GeneralEquation<ScalarEquation<Tscheme> >() { }

/*!
 *  Main constructor.
 *  The scalarfield \c phi_0 defined here is a reference to a global field 
 *  variable. Here \c phi_0 is used as an old value of that field variable. 
 */
  ScalarEquation(ScalarField &phi_global, 
		 DiagMat &matrix, ScalarField &b)
    : GeneralEquation< ScalarEquation<Tscheme> >(phi_global, matrix, b)
  {
    Dim = Typeinfo<Tscheme>::Dim;
    phi_0.reference(phi_global);
    name = "ScalarEquation";
    Gamma = 1.0;
  }

/*!
 *  Main constructor.
 *  The scalarfield \c phi_0 defined here is a reference to a global field 
 *  variable. Here \c phi_0 is used as an old value of that field variable. 
 */
  ScalarEquation(ScalarField &phi_global, 
		 DiagMat &matrix, ScalarField &b,
		 const floatTinyArray_t& deltas)
    : GeneralEquation< ScalarEquation<Tscheme> >(phi_global, matrix, b, deltas)
  {
    Dim = Typeinfo<Tscheme>::Dim;
    phi_0.reference(phi_global);
    name = "ScalarEquation";
    Gamma = 1.0;
  }
  ~ScalarEquation() { }; 
  
/*!
 *  The Curiously Recursive Template Pattern (CRTP) is used.
 *  asDerived() gets an returns a reference to the derived class.
 */
  inline Tscheme& asDerived() { return static_cast<Tscheme&>(*this); }
  
//  
// Set functions used to initialize the parameters.
//
  inline void setGamma(prec_t G) {Gamma = G;}
  inline void setUvelocity(const ScalarField& uu) { u.reference(uu); }
  inline void setVvelocity(const ScalarField& vv) { v.reference(vv); }
  inline void setWvelocity(const ScalarField& ww) { w.reference(ww); }
  
//  
// Get functions
//
  inline ScalarField& get_Phi_0() { return static_cast<ScalarField&>(phi_0);}
/*!
 *  Call to the functions defined in the derived classes.
 */
  inline bool calcCoefficients()
  {
    if(Dim == 1)
      return asDerived().calcCoefficients1D();
    else if (Dim == 2)
      return asDerived().calcCoefficients2D();
    else if (Dim == 3)
      return asDerived().calcCoefficients3D();
  }

///
/// Function to calculate the coefficients of discrete equations for
/// turbulent regime. Turbulent viscosity is passed as argument (nut)
///
  inline bool calcCoefficients(const ScalarField &nut) {
    return asDerived().calcCoefficients(nut);
  }

  inline void printInfo() {
    std::cout << "\n +-----+"
	      << "\n | ScalarEquation< ";
    asDerived().printInfo();
    std::cout << "< " << Dim << "D  > >"
	      << "\n +-----+"
	      << "\n | Gamma = " << Gamma 
	      << "\n +---------------------+\n "; 
  }
  
protected:
  int Dim;
  prec_t Gamma;
  ScalarField u, v, w;
  ScalarField phi_0;

public:

};

}  // namespace Tuna

#endif //_SCALAREQUATION_




